package test.collector;

import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.ScheduleBuilder;
import org.quartz.Scheduler;
import org.quartz.SchedulerMetaData;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.KeyMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import collector.core.CollectConstants;
import collector.core.ConfigTask;
import collector.core.TaskConstVO;
import collector.core.util.JobTaskUtil;
import collector.core.util.ScheduleUtil;
import collector.module.Simple_01_Job;
import collector.module.listener.Simple_01_JobListener;
import collector.task.JobTaskVO;


public class SimpleTriggerExample {

	private static Logger _log = LoggerFactory.getLogger(SimpleTriggerExample.class);
	private static final String _LogPrefixStr = "Sch Log> ";
	List<JobTaskVO> jobTaskList = new ArrayList<JobTaskVO>();

	public void runScheduler() throws Exception {
	    
	    ConfigTask configTask = new ConfigTask();
	    configTask.loadConfigTask(); 
	    configTask.toString();
	    
		_log.info(_LogPrefixStr + "| " + "----- Initializing -------------------");
		Scheduler sched = ScheduleUtil.sf.getScheduler();

		_log.info(_LogPrefixStr + "| " + "----- Initialization Complete --------");

	        _log.info(_LogPrefixStr + "| " + "----- Scheduling Jobs ----------------");

	        JobTaskVO jobTaskVo = null;
	        TaskConstVO tConvVo = null;

//	        // --------------- Job1/1
//	        jobTaskVo = JobTaskUtil.generateJobTask("jobName1", "jobGroup1",  HelloJob.class, "triggerName1", "triggerGroup1", "034200", "MINUTE", 1);
//	        sched = ScheduleUtil.scheduleJobTask(sched, jobTaskVo);
//	        jobTaskList.add(jobTaskVo);
//	        // --------------- Job2/1
//	        jobTaskVo = JobTaskUtil.generateJobTask("jobName2", "jobGroup1",  HelloJob.class, "triggerName2", "triggerGroup1", "014200", "SECOND", 10);
//	        sched = ScheduleUtil.scheduleJobTask(sched, jobTaskVo);
//	        jobTaskList.add(jobTaskVo);
//	        // --------------- Job3/2
//	        jobTaskVo = JobTaskUtil.generateJobTask("jobName3", "jobGroup2",  HelloJob.class, "triggerName3", "triggerGroup2", "011000", "SECOND", 15);
//	        sched = ScheduleUtil.scheduleJobTask(sched, jobTaskVo);
//	        jobTaskList.add(jobTaskVo);
	        
	        Map<String, TaskConstVO> conVoMap = configTask.getConVoMap();
	        
	        // Case for Map Type
	        @SuppressWarnings("rawtypes")
		Iterator itr = conVoMap.keySet().iterator();
	        while (itr.hasNext()) {
	            String keyTaskName = (String)itr.next();
	            tConvVo = conVoMap.get(keyTaskName);
	            	
	            jobTaskVo = JobTaskUtil.generateJobTask(keyTaskName, tConvVo.getTaskGroup(), 
	        	    						tConvVo.getTaskClassStr(), 
	        	    						keyTaskName+"_Trigger", keyTaskName+"_TriggerGroup", 
	        	    						tConvVo.getScheduleDateStr(), tConvVo.getDurationType(), 
	        	    						tConvVo.getDurationValue());
	            sched = ScheduleUtil.scheduleJobTask(sched, jobTaskVo);
	            jobTaskList.add(jobTaskVo);
	            
	        }
	        // Case for List Type
//	        for ( TaskConstVO tConvVo : configTask.getConVoMap() ) {
//	            
//		        jobTaskVo = JobTaskUtil.generateJobTask(tConvVo.getTaskName(), tConvVo.getTaskGroup(),  (Class<? extends Job>) tConvVo.getTaskClass(), tConvVo.getTaskName()+"_Trigger", tConvVo.getTaskName()+"_TriggerGroup", tConvVo.getScheduleDateStr(), tConvVo.getDurationType(), tConvVo.getDurationValue());
//		        sched = ScheduleUtil.scheduleJobTask(sched, jobTaskVo);
//		        jobTaskList.add(jobTaskVo);
//	        }
	        
	        _log.info(_LogPrefixStr + "| " + "jobTaskList="+jobTaskList);
	        
	        _log.info(_LogPrefixStr + "| " + "----- Starting Scheduler ----------------");

	        // All of the jobs have been added to the scheduler, but none of the jobs
	        // will run until the scheduler has been started
	        sched.start();

	        _log.info(_LogPrefixStr + "| " + "----- Started Scheduler -----------------");
	        
	        _log.info(_LogPrefixStr + "| " + "----- Waiting 600 seconds... -------------");
	        try {
	            // wait five minutes to show jobs
	            Thread.sleep(600L * 1000L); 
	            // executing...
	        } catch (Exception e) {
	        }

	        _log.info(_LogPrefixStr + "| " + "----- Shutting Down ---------------------");

	        sched.shutdown(true);

	        _log.info(_LogPrefixStr + "| " + "----- Shutdown Complete -----------------");

	        SchedulerMetaData metaData = sched.getMetaData();
	        _log.info(_LogPrefixStr + "| " + "Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");
	        
	        
	}

	
	    public void runState() throws Exception {

		_log.info("------- Initializing -------------------");

		Scheduler sched = ScheduleUtil.sf.getScheduler();
		
	        ScheduleBuilder<SimpleTrigger> schedBuilder = null;

	        _log.info("------- Initialization Complete --------");

	        _log.info("------- Scheduling Jobs ----------------");

	        // get a "nice round" time a few seconds in the future....
	        Date startTime = nextGivenSecondDate(null, 10);

	        // --------------- Job1
	        startTime = ScheduleUtil.getScheduleRegistTime("034300"); // HHmmss 

	        JobKey jobKey1 = new JobKey("job1", "group1");

		// job1 will only run 5 times (at start time, plus 4 repeats), every 10 seconds
	        JobDetail job1 = newJob(Simple_01_Job.class)
	            .withIdentity(jobKey1)
	            .build();
	    
	        schedBuilder = ScheduleUtil.getScheduleBuilder("MINUTE", 1);
	        
	        SimpleTrigger trigger1 = newTrigger() 
	            .withIdentity("trigger1", "group1")
	            .startAt(startTime)
	            .withSchedule(schedBuilder)
	                    //.withRepeatCount(4))
	            .build();
	        
	        // pass initialization parameters into the job
	        job1.getJobDataMap().put(CollectConstants.EXECUTION_JOBIDS, "Green");
	        job1.getJobDataMap().put(CollectConstants.EXECUTION_RECCOUNT, 1);
	        job1.getJobDataMap().put(CollectConstants.EXECUTION_PREJOBSTATE, 1);

	    	//Listener attached to jobKey
	        sched.getListenerManager().addJobListener(
	    			new Simple_01_JobListener(), KeyMatcher.keyEquals(jobKey1)
	    	);
	    	
	    	//Listener attached to group named "group 1" only.
	    	//scheduler.getListenerManager().addJobListener(
	    	//		new HelloJobListener(), GroupMatcher.jobGroupEquals("group1")
	    	//);
	        
	        // schedule the job to run
	        Date scheduleTime1 = sched.scheduleJob(job1, trigger1);
	        _log.info(job1.getKey() +
	                " will run at: " + scheduleTime1 +  
	                " and repeat: " + trigger1.getRepeatCount() + 
	                " times, every " + trigger1.getRepeatInterval() / 1000 + " seconds");

	        // --------------- Job2
	        startTime = ScheduleUtil.getScheduleRegistTime("034200"); // HHmmss
	        
		JobKey jobKey2 = new JobKey("job2", "group1");
		
	        // job2 will also run 5 times, every 10 seconds
	        JobDetail job2 = newJob(Simple_01_Job.class)
	            .withIdentity(jobKey2)
	            .build();
	    
	        schedBuilder = ScheduleUtil.getScheduleBuilder("SECOND", 10);
	        
	        SimpleTrigger trigger2 = newTrigger() 
	            .withIdentity("trigger2", "group1")
	            .startAt(startTime)
	            .withSchedule(schedBuilder)
	                    //.withRepeatCount(4))
	            .build();

	        // pass initialization parameters into the job
	        // this job has a different favorite color!
	        job2.getJobDataMap().put(CollectConstants.EXECUTION_JOBIDS, "Red");
	        job2.getJobDataMap().put(CollectConstants.EXECUTION_RECCOUNT, 1);
	        job2.getJobDataMap().put(CollectConstants.EXECUTION_PREJOBSTATE, 1);
	        
	    	//Listener attached to jobKey
	        sched.getListenerManager().addJobListener(
	    			new Simple_01_JobListener(), KeyMatcher.keyEquals(jobKey2)
	    	);
	    	
	    	//Listener attached to group named "group 1" only.
	    	//scheduler.getListenerManager().addJobListener(
	    	//		new HelloJobListener(), GroupMatcher.jobGroupEquals("group1")
	    	//);
	        
	        // schedule the job to run
	        Date scheduleTime2 = sched.scheduleJob(job2, trigger2);
	        _log.info(job2.getKey().toString() +
	                " will run at: " + scheduleTime2 +
	                " and repeat: " + trigger2.getRepeatCount() +
	                " times, every " + trigger2.getRepeatInterval() / 1000 + " seconds"); 

	        // --------------- Job3
	        //JobTaskVO jobTaskVo = JobTaskUtil.generateJobTask("jobName", "jobGroup",  Simple_01_Job.class, "triggerName", "triggerGroup", "034200", "MINUTE", 1);
	        JobTaskVO jobTaskVo = JobTaskUtil.generateJobTask("jobName", "jobGroup",  "collector.module.Simple_01_Job", "triggerName", "triggerGroup", "034200", "MINUTE", 1);

	        // pass initialization parameters into the job
	        // this job has a different favorite color!
	        jobTaskVo.setJob( JobTaskUtil.initJob(jobTaskVo.getJob(), "Blue", 1, 1) );
	        
	    	//Listener attached to jobKey
	        
	        sched.getListenerManager().addJobListener(
	    			new Simple_01_JobListener(), KeyMatcher.keyEquals(jobTaskVo.getJobKey())
	    	);
	    	//Listener attached to group named "group 1" only.
//	        sched.getListenerManager().addJobListener(
//	    			new HelloJobListener(), GroupMatcher.jobGroupEquals("group1")
//	    	);
	        
	        // schedule the job to run
	        Date scheduleTime3 = sched.scheduleJob( jobTaskVo.getJob(),  jobTaskVo.getTrigger());
	        jobTaskVo.setScheduleTime(scheduleTime3);	// 스케줄된 시간 세팅
	        _log.info(jobTaskVo.toStringInfoSchedule()); 
//	        _log.info(jobTaskVo.getJobKey().toString() +
//	                " will run at: " + scheduleTime3 +
//	                " and repeat: " + jobTaskVo.getTrigger().getRepeatCount() +
//	                " times, every " + jobTaskVo.getTrigger().getRepeatInterval() / 1000 + " seconds"); 

	        _log.info("------- Starting Scheduler ----------------");

	        // All of the jobs have been added to the scheduler, but none of the jobs
	        // will run until the scheduler has been started
	        sched.start();

	        _log.info("------- Started Scheduler -----------------");
	        
	        _log.info("------- Waiting 600 seconds... -------------");
	        try {
	            // wait five minutes to show jobs
	            Thread.sleep(600L * 1000L); 
	            // executing...
	        } catch (Exception e) {
	        }

	        _log.info("------- Shutting Down ---------------------");

	        sched.shutdown(true);

	        _log.info("------- Shutdown Complete -----------------");

	        SchedulerMetaData metaData = sched.getMetaData();
	        _log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");

	    }

	    public static void main(String[] args) throws Exception {

		SimpleTriggerExample example = new SimpleTriggerExample();
	        //example.runState();
	        example.runScheduler();
	        
	    }
	    
	    public void runSimple() throws Exception {
		
		// JobDetail job = new JobDetail();
		// job.setName("dummyJobName");
		// job.setJobClass(HelloJob.class);

		JobDetail job = JobBuilder.newJob(Simple_01_Job.class)
				.withIdentity("dummyJobName", "group1").build();

		// SimpleTrigger trigger = new SimpleTrigger();
		// trigger.setStartTime(new Date(System.currentTimeMillis() + 1000));
		// trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
		// trigger.setRepeatInterval(30000);

		// Trigger the job to run on the next round minute
		Trigger trigger = TriggerBuilder
				.newTrigger()
				.withIdentity("dummyTriggerName", "group1")
				.withSchedule(
						SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInSeconds(5).repeatForever())
				.build();

		// schedule it
		Scheduler scheduler = new StdSchedulerFactory().getScheduler();
		scheduler.start();
		scheduler.scheduleJob(job, trigger);

	}
}
